<template>
  <Modal
    v-model="showCreateTestcaseModal"
    title="创建用例"
    :mask-closable="false"
    :closable="false"
    fullscreen
    @on-cancel="handleCreateTestcaseCancel(false)"
  >
    <Form
      label-position="right"
      :label-width="100"
      ref="testcaseForm"
      :model="testcaseForm"
      :rules="testcaseValidate"
    >
      <Tabs name="testcase-add-tabs" :animated="true">
        <TabPane label="基础信息" tab="testcase-add-tabs">
          <FormItem label="用例名称" prop="name">
            <Input clearable v-model="testcaseForm.name" />
          </FormItem>
          <FormItem label="所属项目">
            <div style="display: flex">
              <Select
                clearable
                @on-change="changeProjectOption"
                v-model="project"
              >
                <Option
                  v-for="item in projects"
                  :value="item.id"
                  :key="item.id"
                  >{{ item.name }}</Option
                >
              </Select>
              <Button
                type="text"
                icon="ios-refresh"
                style="color: #2d8cf0"
                @click="getProjectNames"
                >刷新</Button
              >
            </div>
          </FormItem>
          <FormItem label="关联接口" prop="api">
            <Select
              filterable
              clearable
              transfer
              placeholder="请先选择所属项目"
              v-model="testcaseForm.api"
              @on-change="changeApiOption"
            >
              <Option
                v-for="item in apis"
                :key="item.id"
                :value="item.id"
                :label="item.name"
              >
                <span>{{ item.name }}</span>
                <span style="float: right; color: #ccc"
                  >{{ item.url }} — {{ item.method }}</span
                >
              </Option>
            </Select>
          </FormItem>
          <FormItem label="请求URL" prop="url">
            <Input v-model="testcaseForm.url" />
          </FormItem>
          <FormItem label="备注">
            <Input
              type="textarea"
              clearable
              v-model="testcaseForm.remark"
              :rows="10"
            />
          </FormItem>
        </TabPane>
        <TabPane label="Headers参数" tab="testcase-add-tabs">
          <div class="radio-group">
            <span class="radio-group-item">Content-Type</span>
            <RadioGroup
              v-model="contentType"
              @on-change="changeHeaderRadio('Content-Type', contentType)"
            >
              <Radio label="无" class="radio-group-item"></Radio>
              <Radio label="application/json" class="radio-group-item"></Radio>
              <Radio
                label="application/x-www-form-urlencoded"
                class="radio-group-item"
              ></Radio>
            </RadioGroup>
          </div>
          <div class="radio-group">
            <span class="radio-group-item">Authorization</span>
            <RadioGroup
              v-model="authorization"
              @on-change="changeHeaderRadio('Authorization', authorization)"
            >
              <Radio label="无" class="radio-group-item"></Radio>
              <Radio label="Bearer Token" class="radio-group-item"></Radio>
            </RadioGroup>
          </div>
          <JsonEditor
            v-model="testcaseForm.headers"
            jsonEditorId="createTestcaseHeaders"
            style="height: 700px"
          ></JsonEditor>
        </TabPane>
        <TabPane :label="bodyTabPaneLabel" tab="testcase-add-tabs">
          <FormItem label="参数类型" :label-width="80" prop="request_data_type">
            <RadioGroup v-model="testcaseForm.request_data_type">
              <Radio label="Json"></Radio>
              <Radio label="Form Data"></Radio>
            </RadioGroup>
          </FormItem>
          <JsonEditor
            v-model="testcaseForm.request_data"
            jsonEditorId="createTestcaseRequestData"
            style="height: 700px"
          ></JsonEditor>
        </TabPane>
        <TabPane label="期望结果" tab="testcase-add-tabs">
          <div class="button-group">
            <Button
              type="primary"
              class="button-group-item"
              @click="showExpectResultEditDrawer"
              >用例断言 | 提取变量</Button
            >
          </div>
          <JsonEditor
            v-model="testcaseForm.expect_result"
            jsonEditorId="createTestcaseExpectResult"
            style="height: 720px"
          ></JsonEditor>
        </TabPane>
      </Tabs>
    </Form>
    <div slot="footer">
      <Button type="default" @click="handleCreateTestcaseCancel(false)"
        >取消</Button
      >
      <Button type="primary" @click="handleCreateTestcaseSubmit('testcaseForm')"
        >确定</Button
      >
    </div>
    <ExpectResultEdit
      :showDrawer.sync="showDrawer"
      :expectResult.sync="tempExpectResult"
      @updateExpectResult="updateExpectResult"
    ></ExpectResultEdit>
  </Modal>
</template>

<script>
import { createTestcase } from "@/api/HttpAutoTestService/testcase";
import { getProjectNames } from "@/api/HttpAutoTestService/project";
import { getApiNames, getApiById } from "@/api/HttpAutoTestService/api";
import JsonEditor from "_c/json-editor";
import ExpectResultEdit from "./expect-result-edit";

export default {
  name: "testcase-create",
  components: {
    JsonEditor,
    ExpectResultEdit,
  },
  props: {
    createTestcase: {
      type: Boolean,
      default: false,
    },
    apiId: {
      type: String,
      default: "",
    },
    // 用例复制
    testcase: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
  watch: {
    createTestcase(val) {
      if (val) {
        this.getProjectNames();
      }
    },
    apiId(val) {
      // 从接口创建测试用例
      if (this.showCreateTestcaseModal) {
        if (val !== undefined && val !== "") {
          this.testcaseForm.api = val;
          getApiById(val).then((res) => {
            let data = res.data;
            this.project = data.project.id;
            // 执行选择项目的伪操作
            this.changeProjectOption(this.project);
            this.testcaseForm.name = data.name;
            let url = data.url;
            let request_params = data.request_params;
            this.testcaseForm.url = url;
            if (request_params) {
              this.testcaseForm.url = url + "?" + request_params;
            }
            this.testcaseForm.request_data_type = data.request_data_type;
            this.testcaseForm.request_params = "";
            this.testcaseForm.headers = data.headers;
            this.testcaseForm.request_data = data.request_data;
          });
        }
      }
    },
    testcase(val) {
      // 复制测试用例
      if (this.showCreateTestcaseModal) {
        if (JSON.stringify(val) !== "{}") {
          this.project = val.project;
          this.testcaseForm = { ...val };
          delete this.testcaseForm["project"];
          // 执行选择项目的伪操作
          this.changeProjectOption(this.project);
        }
      }
    },
  },
  computed: {
    showCreateTestcaseModal: {
      get() {
        return this.createTestcase;
      },
      set(val) {
        this.$emit("update:createTestcase", val);
        this.$emit("update:apiId", "");
        this.$emit("update:testcase", {});
      },
    },
    bodyTabPaneLabel() {
      return `Body参数（${this.testcaseForm.request_data_type})`;
    },
  },
  data() {
    return {
      showDrawer: false,
      project: "",
      testcaseForm: {
        name: "",
        api: "",
        url: "",
        headers: { "Content-Type": "application/json" },
        request_data_type: "Json",
        request_params: "",
        request_data: {},
        expect_result: {
          output: [],
          validate: [{ check: "status_code", expect: 200, comparator: "eq" }],
        },
        remark: "",
      },
      testcaseValidate: {
        name: [{ required: true, message: "请输入用例名称", trigger: "blur" }],
        api: [{ required: true, message: "请选择关联接口", trigger: "change" }],
        url: [{ required: true, message: "请输入请求URL", trigger: "blur" }],
        request_data_type: [
          { required: true, message: "请选择参数类型", trigger: "change" },
        ],
      },
      projects: [],
      apis: [],
      testcases: [],
      contentType: "application/json",
      authorization: "无",
      tempExpectResult: {},
    };
  },
  methods: {
    handleCreateTestcaseCancel(continueCreate) {
      this.testcaseForm = {
        name: "",
        api: "",
        url: "",
        headers: { "Content-Type": "application/json" },
        request_data_type: "Json",
        request_params: "",
        request_data: {},
        expect_result: {
          output: [],
          validate: [{ check: "status_code", expect: 200, comparator: "eq" }],
        },
        remark: "",
      };
      this.$refs["testcaseForm"].resetFields();
      if (!continueCreate) {
        // 不再继续创建用例，关闭弹框，刷新列表
        this.project = "";
        this.projects = [];
        this.apis = [];
        this.showCreateTestcaseModal = false;
        this.$emit("initTestcaseTable");
        this.$emit("initApiTable");
      }
    },
    handleCreateTestcaseSubmit(name) {
      this.$refs[name].validate((valid) => {
        if (valid) {
          let tempTestcase = { ...this.testcaseForm };
          tempTestcase.url = tempTestcase.url.trim();
          // url以/开始
          let index1 = tempTestcase.url.indexOf("/");
          if (index1 === 0) {
            let tempUrl = tempTestcase.url;
            tempTestcase.url = tempUrl.slice(index1 + 1);
          }
          // url中包含?,?之后的参数代表请求参数
          let index2 = tempTestcase.url.indexOf("?");
          if (index2 !== -1) {
            let tempUrl = tempTestcase.url;
            tempTestcase.url = tempUrl.slice(0, index2);
            tempTestcase.request_params = tempUrl.slice(index2 + 1);
          }

          if (this.testcaseForm.headers === "") {
            this.testcaseForm.headers = {};
          }

          if (this.testcaseForm.request_data === "") {
            this.testcaseForm.request_data = {};
          }

          if (this.testcaseForm.expect_result === "") {
            this.testcaseForm.expect_result = {};
          }
          createTestcase(this.testcaseForm)
            .then((res) => {
              if (res.status === 201) {
                let config = {
                  title: "创建成功",
                  content: "是否继续创建？？？",
                  okText: "继续",
                  onOk: () => {
                    this.handleCreateTestcaseCancel(true);
                  },
                  onCancel: () => {
                    this.handleCreateTestcaseCancel(false);
                  },
                };
                this.$Modal.confirm(config);
              } else {
                this.$Message.error("创建失败");
              }
            })
            .catch((err) => {
              this.$Modal.error({
                title: "系统异常，请联系管理员……",
                content: JSON.stringify(err),
                closable: true,
              });
            });
        }
      });
    },
    getProjectNames() {
      getProjectNames()
        .then((res) => {
          this.projects = res.data;
        })
        .catch((err) => {
          this.$Modal.error({
            title: "系统异常，请联系管理员……",
            content: JSON.stringify(err),
            closable: true,
          });
        });
    },
    getApiNames() {
      getApiNames({ detail: true })
        .then((res) => {
          this.apis = res.data;
        })
        .catch((err) => {
          this.$Modal.error({
            title: "系统异常，请联系管理员……",
            content: JSON.stringify(err),
            closable: true,
          });
        });
    },
    changeProjectOption(val) {
      if (val !== undefined) {
        getApiNames({ detail: true, project: val }).then((res) => {
          this.apis = res.data;
          if (Array.isArray(this.apis)) {
            let apisTemp = this.apis.filter((item) => {
              return this.testcaseForm.api === item.id;
            });
            if (apisTemp.length === 0) {
              this.testcaseForm.api = "";
            }
          }
        });
        return;
      }
      getApiNames({ detail: true }).then((res) => {
        this.apis = res.data;
      });
    },
    changeApiOption(val) {
      if (val !== undefined && val !== "") {
        this.testcaseForm.request_data_type = "";
        let api = this.apis.filter((item) => {
          return item.id === val;
        });
        let url = api[0].url;
        let request_params = api[0].request_params;
        if (request_params) {
          url = url + "?" + request_params;
        }
        this.testcaseForm.url = url;
        this.testcaseForm.headers = api[0].headers;
        this.testcaseForm.request_data_type = api[0].request_data_type;
        this.testcaseForm.request_params = "";
        this.testcaseForm.request_data = api[0].request_data;
      } else {
        this.testcaseForm.url = "";
        this.testcaseForm.request_data_type = "Json";
        this.testcaseForm.request_params = "";
        this.testcaseForm.request_data = {};
      }
    },
    // 更改请求头的Content-Type、Authorization内容
    changeHeaderRadio(property, value) {
      let headers = { ...this.testcaseForm.headers };
      if (value === "无") {
        delete headers[property];
      } else {
        if (property === "Content-Type") {
          headers["Content-Type"] = this.contentType;
        } else if (property === "Authorization") {
          headers["Authorization"] = this.authorization;
        }
      }
      this.testcaseForm.headers = headers;
    },
    showExpectResultEditDrawer() {
      this.tempExpectResult = this.testcaseForm.expect_result;
      this.showDrawer = true;
    },
    updateExpectResult(expectResult) {
      this.testcaseForm.expect_result = { ...expectResult };
    },
  },
};
</script>

<style scoped lang="less">
span {
  font-size: 14px;
  font-weight: bold;
  color: #464c5b;
}
.radio-group {
  display: flex;
  align-items: center;
  .radio-group-item {
    margin: 0 20px 20px 0;
  }
}
.button-group {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  .button-group-item {
    margin: 0 0 10px 10px;
  }
}
</style>

